package main

import (
	"flag"
	"fmt"
	"log"
	"os"
)

// CLI 命令行接口结构
type CLI struct{}

// printUsage 打印使用方法
func (cli *CLI) printUsage() {
	fmt.Println("使用方法:")
	fmt.Println("  addblock -data BLOCK_DATA - 向区块链添加区块")
	fmt.Println("  printchain - 打印所有区块")
	fmt.Println("  getbalance -address ADDRESS - 获取地址余额")
	fmt.Println("  createblockchain -address ADDRESS - 创建区块链")
	fmt.Println("  send -from FROM -to TO -amount AMOUNT - 发送交易")
}

// validateArgs 验证参数
func (cli *CLI) validateArgs() {
	if len(os.Args) < 2 {
		cli.printUsage()
		os.Exit(1)
	}
}

// printChain 打印区块链
func (cli *CLI) printChain() {
	bc := NewBlockchain()
	defer bc.db.Close()

	bci := bc.Iterator()

	for {
		block := bci.Next()

		fmt.Printf("============ 区块 %x ============\n", block.Hash)
		fmt.Printf("前一个区块哈希: %x\n", block.PrevHash)
		fmt.Printf("数据: %s\n", block.Data)
		fmt.Printf("时间戳: %d\n", block.Timestamp)
		fmt.Printf("Nonce: %d\n", block.Nonce)

		pow := NewProofOfWork(block)
		fmt.Printf("PoW验证: %t\n", pow.Validate())
		fmt.Printf("\n")

		if len(block.PrevHash) == 0 {
			break
		}
	}
}

// addBlock 添加区块
func (cli *CLI) addBlock(data string) {
	bc := NewBlockchain()
	defer bc.db.Close()

	bc.AddBlock(data)
	fmt.Println("成功添加区块!")
}

// Run 命令行接口入口
func (cli *CLI) Run() {
	cli.validateArgs()

	addBlockCmd := flag.NewFlagSet("addblock", flag.ExitOnError)
	printChainCmd := flag.NewFlagSet("printchain", flag.ExitOnError)

	addBlockData := addBlockCmd.String("data", "", "区块数据")

	switch os.Args[1] {
	case "addblock":
		err := addBlockCmd.Parse(os.Args[2:])
		if err != nil {
			log.Panic(err)
		}
	case "printchain":
		err := printChainCmd.Parse(os.Args[2:])
		if err != nil {
			log.Panic(err)
		}
	default:
		cli.printUsage()
		os.Exit(1)
	}

	if addBlockCmd.Parsed() {
		if *addBlockData == "" {
			addBlockCmd.Usage()
			os.Exit(1)
		}
		cli.addBlock(*addBlockData)
	}

	if printChainCmd.Parsed() {
		cli.printChain()
	}
}
